package com.xiaouyudeguang.common.runner;

import com.xiaouyudeguang.common.entity.Column;
import com.xiaouyudeguang.common.entity.Table;
import com.xiaouyudeguang.common.handler.TableHandler;
import com.xiaouyudeguang.common.utils.CollectUtils;
import com.xiaouyudeguang.common.utils.FreeMarkerUtils;
import com.xiaouyudeguang.common.utils.RequestUtils;
import com.xiaouyudeguang.common.utils.StringUtils;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.maven.model.Model;
import org.apache.maven.model.io.xpp3.MavenXpp3Reader;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.HttpServletRequest;
import java.io.File;
import java.io.FileReader;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

@Data
@Slf4j
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class CodeRunner {

    private Map<String, Table> tableMap = new HashMap<>();

    private static final String java_path = "/src/main/java/";

    private static final String resources_path = "/src/main/resources";

    private String absolutePath;

    private String templatePath;

    private String group;

    private String module;

    private String basePackage;

    private String tableName;

    private String comment;

    private Map<String, String> columns;

    private boolean toPinyin;

    public boolean execute() throws Exception {
        if (tableMap == null || !tableMap.containsKey(tableName)) {
            tableMap = TableHandler.getTables().stream().collect(Collectors.toMap(Table::getTableName, Table -> Table));
        }
        Table table = tableMap.get(tableName);
        List<Column> columnList = new ArrayList<>();
        if (table != null && CollectUtils.isNotEmpty(columns)) {
            columnList = table.getColumns();
            for (Column column : columnList) {
                column.setColumnType(column.getColumnType().toLowerCase());
                if (columns.containsKey(column.getFieldName())) {
                    String comment = columns.get(column.getFieldName());
                    if (StringUtils.isNotBlank(comment)) {
                        column.setComment(comment);
                        columns.remove(column.getFieldName());
                    }
                } else {
                    String comment = columns.get(column.getComment());
                    if (StringUtils.isNotBlank(comment)) {
                        column.setComment(comment);
                        columns.remove(column.getComment());
                    }
                }
            }
        }
        columnList.addAll(Column.getColumns(columns, toPinyin));
        return execute(tableName, comment, columnList);
    }

    public boolean execute(String tableName, String comment, List<Column> columns) throws Exception {
        if (tableMap == null || !tableMap.containsKey(tableName)) {
            tableMap = TableHandler.getTables().stream().collect(Collectors.toMap(Table::getTableName, Table -> Table));
        }
        Table table = tableMap.get(tableName);
        if (table == null) {
            TableHandler.createTableSQL(tableName, comment);
            execute(tableName, comment, columns);
        } else {
            table.setColumns(columns);
            execute(table);
        }
        return true;
    }

    public static HttpServletRequest getRequest() {
        try {
            return ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
        } catch (Exception e) {
            return null;
        }
    }

    private boolean execute(Table table) throws Exception {
        absolutePath = absolutePath != null ? absolutePath : System.getProperty("user.dir").replace("\\", "/");
        if (RequestUtils.getRequest() == null) {
            absolutePath = absolutePath.substring(0, absolutePath.lastIndexOf("/"));
        }
        templatePath = templatePath != null ? templatePath : Objects.requireNonNull(CodeRunner.class.getResource("")).getPath().toString().replace("file:/", "");
        if (templatePath.contains("/")) {
            templatePath = "/" + templatePath;
        }
        String tablePath = table.getTableName();
        String templateFile = templatePath.replace("\\", "/").substring(0, templatePath.indexOf(".jar")) + "/dm";
        String basePath = absolutePath + "/" + group + "-" + module;
        String apiPath = basePath + "/" + group + "-" + module + "-api";
        String apiPackagePath = apiPath + java_path + basePackage.replace(".", "/");
        String srvPath = basePath + "/" + group + "-" + module + "-srv";
        String srvPackagePath = srvPath + java_path + basePackage.replace(".", "/");
        String srvResourcePath = srvPath + resources_path;
        String pom = absolutePath + File.separator + "pom.xml";
        MavenXpp3Reader reader = new MavenXpp3Reader();
        Model model = reader.read(new FileReader(pom));

        Map input = new HashMap<>();
        input.put("moduleGroup", group);
        input.put("moduleName", group + "-" + module);
        input.put("moduleArtifactId", model.getArtifactId());
        input.put("package", basePackage);
        input.put("tablePath", basePackage + "." + tablePath);
        input.put("author", System.getProperty("user.name"));
        input.put("dateTime", new SimpleDateFormat("yyyy-MM-dd").format(new Date()));
        log.info("正在创建表" + table.getTableName() + "对应的业务类...");
        input.put("table", table);
        input.put("lowerClassName", StringUtils.lowerName(table.getClassName()));
        FreeMarkerUtils.genteratorFile(input, templateFile, "Api.java", apiPackagePath + "/" + tablePath + "/api/", table.getClassName() + "Api.java");
        FreeMarkerUtils.genteratorFile(input, templateFile, "Entity.java", apiPackagePath + "/" + tablePath + "/entity/", table.getClassName() + ".java");
        FreeMarkerUtils.genteratorFile(input, templateFile, "Resource.java", srvPackagePath + "/" + tablePath + "/resource/", table.getClassName() + "Resource.java");
        FreeMarkerUtils.genteratorFile(input, templateFile, "Dao.java", srvPackagePath + "/" + tablePath + "/dao/", table.getClassName() + "Dao.java");
        FreeMarkerUtils.genteratorFile(input, templateFile, "Service.java", srvPackagePath + "/" + tablePath + "/service/", table.getClassName() + "Service.java");
        FreeMarkerUtils.genteratorFile(input, templateFile, "ServiceImpl.java", srvPackagePath + "/" + tablePath + "/service/impl/", table.getClassName() + "ServiceImpl.java");
        FreeMarkerUtils.genteratorFile(input, templateFile, "Resource.java", srvPackagePath + "/" + tablePath + "/resource/", table.getClassName() + "Resource.java");
        FreeMarkerUtils.genteratorFile(input, templateFile, "ApiConstants.java", apiPackagePath + "/constants/", "ApiConstants.java", false);
        FreeMarkerUtils.genteratorFile(input, templateFile, "pom.xml", basePath, "pom.xml", false);
        FreeMarkerUtils.genteratorFile(input, templateFile, "pom-api.xml", apiPath, "pom.xml", false);
        FreeMarkerUtils.genteratorFile(input, templateFile, "pom-api.xml", apiPath, "pom.xml", false);
        FreeMarkerUtils.genteratorFile(input, templateFile, "pom-srv.xml", srvPath, "pom.xml", false);
        FreeMarkerUtils.genteratorFile(input, templateFile, "bootstrap.yml", srvResourcePath, "bootstrap.yml", false);
        FreeMarkerUtils.genteratorFile(input, templateFile, "logback.xml", srvResourcePath, "logback.xml", false);
        FreeMarkerUtils.genteratorFile(input, templateFile, "log4jdbc.log4j2.properties", srvResourcePath, "log4jdbc.log4j2.properties", false);
        FreeMarkerUtils.genteratorFile(input, templateFile, "StartApp.java", srvPackagePath, "StartApp.java", false);
        log.info("完成创建表" + table.getTableName() + "对应的业务类...");
        return true;
    }
}